package main

import (
	//"bufio"
	//"database/sql"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"github.com/buaazp/fasthttprouter"
	//"github.com/mediocregopher/radix.v2/pool"
	//"github.com/mediocregopher/radix.v2/redis"
	//_ "github.com/go-sql-driver/mysql"
	//"bytes"
	"github.com/valyala/fasthttp"
	//"io/ioutil"
	//"os"
	"regexp"
	"strconv"
	//"strings"
	//"time"
	"crypto/md5"
	"encoding/xml"
	"log"
	"os"
)

const (
	log_file_name = "quicksdk_pay_57.log"
	timelayout    = "2006-01-02 15:04:05"
	cb_key_57     = "83837305545985828739934355506355"
	md5_key       = "hnppju0jjwia58qtumns8fcjoior7lxo"

	appID_57      = "105"
	encryptKey_57 = "S4WcuAc05vTpohOErYoF"
	CNY           = "CNY"
)

var (
	mylog      *log.Logger
	output_url = "http://lszhcn.fantasykk.com:9000/AliPayNotify"
	//output_url = "http://127.0.0.1:5777/_test2"
)

func randStr(n int) string {
	b := make([]byte, n)
	if _, err := rand.Read(b); err != nil {
		panic(err)
	}
	return hex.EncodeToString(b)
}

func assertFail(should_ok bool, errNo int) {
	if !should_ok {
		panic(errNo)
	}
}

func OnPanic(ctx *fasthttp.RequestCtx) {
	if r := recover(); r != nil {
		fmt.Fprintf(ctx, "error:%d", r)
		fmt.Println("OnPanic", r)
	}
}

func F_rootPage(ctx *fasthttp.RequestCtx) {
	defer OnPanic(ctx)

	fmt.Fprint(ctx, "NOT Welcome!\n")

	fmt.Fprintf(ctx, "Request method is %q\n", ctx.Method())
	fmt.Fprintf(ctx, "RequestURI is %q\n", ctx.RequestURI())
	fmt.Fprintf(ctx, "Requested path is %q\n", ctx.Path())
	fmt.Fprintf(ctx, "Host is %q\n", ctx.Host())
	fmt.Fprintf(ctx, "Query string is %q\n", ctx.QueryArgs())
	fmt.Fprintf(ctx, "User-Agent is %q\n", ctx.UserAgent())
	fmt.Fprintf(ctx, "Connection has been established at %s\n", ctx.ConnTime())
	fmt.Fprintf(ctx, "Request has been started at %s\n", ctx.Time())
	fmt.Fprintf(ctx, "Serial request number for the current connection is %d\n", ctx.ConnRequestNum())
	fmt.Fprintf(ctx, "Your ip is %q\n\n", ctx.RemoteIP())

	fmt.Fprintf(ctx, "Raw request is:\n---CUT---\n%s\n---CUT---", &ctx.Request)

	ctx.SetContentType("text/plain; charset=utf8")

	// Set arbitrary headers
	ctx.Response.Header.Set("X-My-Header", "my-header-value")

	// Set cookies
	var c fasthttp.Cookie
	c.SetKey("cookie-name")
	c.SetValue("cookie-value")
	ctx.Response.Header.SetCookie(&c)
}

func F_test2(ctx *fasthttp.RequestCtx) {
	fmt.Printf("Requested path is %q\n", string(ctx.Path()))
	fmt.Printf("Post string is %q\n", ctx.PostArgs())

	fmt.Fprintf(ctx, "fail")
}

type Layer2 struct {
	Vis_test       string `xml:"is_test"`
	Vchannel       string `xml:"channel"`
	Vchannel_name  string `xml:"channel_name"`
	Vchannel_uid   string `xml:"channel_uid"`
	Vgame_order    string `xml:"game_order"`
	Vorder_no      string `xml:"order_no"`
	Vpay_time      string `xml:"pay_time"`
	Vamount        string `xml:"amount"`
	Vstatus        string `xml:"status"`
	Vextras_params string `xml:"extras_params"`
}

type Layer1 struct {
	XMLName xml.Name `xml:"quicksdk_message"`
	Vmes    Layer2   `xml:"message"`
}

func F_quicksdk_pay(ctx *fasthttp.RequestCtx) {
	defer OnPanic(ctx)

	post_args := ctx.PostArgs()
	//remote_ip := ctx.RemoteIP()
	data1 := post_args.Peek("nt_data")
	sign := post_args.Peek("sign")
	md5Sign := post_args.Peek("md5Sign")

	// yan qian
	to_yan := append(data1, sign...)
	to_yan = append(to_yan, []byte(md5_key)...)
	qian := fmt.Sprintf("%x", md5.Sum(to_yan))

	fmt.Println("md5Sign:", string(md5Sign))
	fmt.Println("md5Sign we calc:", qian)

	assertFail(string(md5Sign) == qian, 101)

	// yan qian PASS, decode
	pattern1 := regexp.MustCompile("@[0-9]+")
	aa := pattern1.FindAll(data1, 9999)

	minwen_buf := make([]byte, 0, 512)
	cb_key2 := []byte(cb_key_57)
	for i := 0; i < len(aa); i++ {
		s := aa[i]
		s = s[1:len(s)]
		n, _ := strconv.Atoi(string(s))
		b := n - int(0xff&cb_key2[i%len(cb_key2)])
		minwen_buf = append(minwen_buf, byte(b))
	}

	// log it first
	minwen := string(minwen_buf)
	mylog.Println(minwen)
	fmt.Println(minwen)

	// try decode XML
	v := Layer1{}
	err := xml.Unmarshal(minwen_buf, &v)
	assertFail(nil == err, 102)

	fmt.Println(v)

	// make request for 57 egls
	post_args.Reset()
	post_args.Add("appId", appID_57)
	post_args.Add("cpOrder", v.Vmes.Vgame_order)
	post_args.Add("money", v.Vmes.Vamount)
	post_args.Add("payTime", v.Vmes.Vpay_time)
	post_args.Add("order", v.Vmes.Vorder_no)
	post_args.Add("currency", CNY)
	post_args.Add("sandbox", v.Vmes.Vis_test)

	tt := appID_57 + "&" + v.Vmes.Vgame_order + "&" + CNY + "&" + v.Vmes.Vamount + "&" + v.Vmes.Vorder_no + "&" + v.Vmes.Vpay_time + "&" + v.Vmes.Vis_test
	tt += encryptKey_57
	encrypted := fmt.Sprintf("%x", md5.Sum([]byte(tt)))
	post_args.Add("sign", encrypted)

	_, body2, err := fasthttp.Post(nil, output_url, post_args)
	assertFail(nil == err, 103)

	body2str := string(body2)
	fmt.Println("REQ return:", body2str)
	if "success" == body2str {
		fmt.Fprintf(ctx, "SUCCESS")
	} else {
		fmt.Fprintf(ctx, body2str)
	}
}

func main() {
	fh, err := os.OpenFile(log_file_name, os.O_APPEND, 0666)
	if nil != err {
		fh, err = os.Create(log_file_name)
		if nil != err {
			panic(err)
		}
	}

	log1 := log.New(fh, "quicksdk57|", log.LstdFlags)
	mylog = log1

	our_router := fasthttprouter.New()

	our_router.GET("/bbbbb", F_rootPage)

	our_router.POST("/", F_quicksdk_pay)
	our_router.POST("/_test2", F_test2)

	log.Fatal(fasthttp.ListenAndServe(":5777", our_router.Handler))
}
